package servidor;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.exception.ConstraintViolationException;

import br.ufpi.domain.Pergunta;
import br.ufpi.domain.Resposta;
import br.ufpi.domain.Usuario;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.Calendar;
import java.util.Date;
import ufpi.br.dao.PerguntaDao;
import ufpi.br.dao.RespostaDao;
import ufpi.br.dao.UsuarioDao;
import util.Email;
import util.ProtocoloMensagem;

public class AppServidor {

    @SuppressWarnings("unchecked")
    static ProtocoloMensagem protocoloMensagem;

    public static void main(String argv[]) throws Exception {
        protocoloMensagem = new ProtocoloMensagem();
        ServerSocket servidor = new ServerSocket(cliente.gui.LoginGUI.PORTA);
        System.out.println("Servidor Iniciado, aguardando conexao...\n\n");
        while (true) {
            Socket conexao = servidor.accept();

            // Conexao para receber os dados do cliente
            DataInputStream in = new DataInputStream(conexao.getInputStream());
            // Conexao para enviar os dados do cliente
            DataOutputStream out = new DataOutputStream(
                    conexao.getOutputStream());
            String objetoRecebido = in.readUTF();
            String[] mensagemRecebida = protocoloMensagem.decodificar(objetoRecebido);
            if (mensagemRecebida[0].equals("CADA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para cadastro de usuario");
                cadastrarUsuario(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("LOGIN")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao de login");
                loginUsuario(mensagemRecebida[1], mensagemRecebida[2], out);
            } else if (mensagemRecebida[0].equals("ALTERARUSUARIO")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao alterar usuario");
                alterarUsuario(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("ENVIARPERGUNTA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para enviar pergunta");
                receberPerguntaEnviada(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("GETPERG")) {
                System.out.println("["
                        + conexao.getInetAddress()
                        + "]--Recebida solicitacao para pegar Minhas perguntas");
                System.out.println(objetoRecebido);
                getPerguntas(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("USUGET")) {
                System.out.println("["
                        + conexao.getInetAddress()
                        + "]--Recebida solicitacao para pegar usuario do sistema");
                getUsuario(mensagemRecebida[1], out);
            } else if (mensagemRecebida[0].equals("ALTERARSENHA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para Alterar Senha");
                alterarSenha(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("GETRESPOSTASPERGUTA")) {
                System.out.println("["
                        + conexao.getInetAddress()
                        + "]--Recebida solicitacao de Todasrespostas de uma pergunta");
                getRespostadePergunta(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("LISTARPERGUNTAS")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao de Listar todas perguntas");

                getTodasPerguntas(Boolean.parseBoolean(mensagemRecebida[1]),
                        out);
            } else if (mensagemRecebida[0].equals("GETPONTUACAO")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para LreceberPontuação");
                getPontuacao(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("RESPONDERPERGUNTA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao de Responder Pergunta");
                responderPergunta(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("GETPERGUNTASBYSTATUS")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para RECEBER PERGUNTAS POR STATUS");
                getPerguntasStatus(mensagemRecebida, out);
            } else if (mensagemRecebida[0].equals("GETRESPOSTASBYSTATUS")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para RECEBER RESPOSTAS POR STATUS");
                getRespostasStatus(mensagemRecebida, out);
            }
            if (mensagemRecebida[0].equals("GETUSUARIOSNOTA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para Nota dos 10 melhores usuarios");
                getNotasUsuarios(mensagemRecebida, out);
            }
            if (mensagemRecebida[0].equals("GETRESPOSTASNOTA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para RECEBER assert 10 Melhores Respostas;");
                getRespostasNota(mensagemRecebida, out);
            } //--------------------- Feito por AerS -----------------/
            else if (mensagemRecebida[0].equals("GETUSUARIOSACEITOS")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para Listar Usuarios Cadastrados");
                getUsuariosAceitos(out);
            } else if (mensagemRecebida[0].equals("GETUSUARIOSPENDENTES")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para Listar Usuarios Pendentes");
                getUsuariosPendentes(out);
            } else if (mensagemRecebida[0].equals("ATUALIZARUSUARIO")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para atualizar usuario");
                atualizarUsuario(objetoRecebido, out);
            } else if (mensagemRecebida[0].equals("ADMINLISTARPERGUNTAS")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para listar perguntas");
                adminListarPerguntas(mensagemRecebida[1], out);
            } else if (mensagemRecebida[0].equals("ATUALIZARSTATUSPERGUNTA")) {
                Long perguntaId = Long.parseLong(mensagemRecebida[1]);
                int status = Integer.parseInt(mensagemRecebida[2]);
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para atualizar perguntas");
                atualizarStatusPergunta(perguntaId, status, out);
            } else if (mensagemRecebida[0].equals("ADMINLISTARRESPOSTAS")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para admin listar respostas");
                adminListarRespostas(mensagemRecebida[1], mensagemRecebida[2], out);
            } else if (mensagemRecebida[0].equals("COMENTARPERGUNTA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para comentar pergunta");
                comentarPergunta(mensagemRecebida[1], mensagemRecebida[2], out);
            } else if (mensagemRecebida[0].equals("COMENTARRESPOSTA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para comentar pergunta");
                comentarResposta(mensagemRecebida[1], mensagemRecebida[2], out);
            } else if (mensagemRecebida[0].equals("ADMINATUALIZARRESPOSTA")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para atualizar resposta");
                adminAtualizarResposta(mensagemRecebida[1], mensagemRecebida[2], mensagemRecebida[3], out);
            } else if (mensagemRecebida[0].equals("LISTARUSUARIOCOMPONTUACAO")) {
                System.out.println("[" + conexao.getInetAddress()
                        + "]--Recebida solicitacao para listarUsuarios com pontuacao");
                adminListarUsuarioComPontuacao(objetoRecebido, out);
            }

            in.close();
            out.close();
        }

    }

    private static void getTodasPerguntas(boolean isAdmin, DataOutputStream out) {
        PerguntaDao dao = new PerguntaDao();
        ArrayList<Pergunta> perguntas;

        if (isAdmin) {
            perguntas = (ArrayList<Pergunta>) dao.listAll();
        } else {
            perguntas = dao.getPerguntasAceitas();
        }
        String mensagemSaida = protocoloMensagem.codificarPerguntas(perguntas, perguntas.size());
        try {
            out.writeUTF(mensagemSaida);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Se nao existir ninguem cadastrado no BD, o primeiro cadastro efetuado vai
     * ser Administrador(Professor) isPendente=false && isAdmin=true Senao, o
     * cadastro vai ser efetuado normalmente
     */
    private static void cadastrarUsuario(String[] cadastro, DataOutputStream out) {

        Usuario usuario = new Usuario();
        usuario.setMatricula(cadastro[1]);
        usuario.setNomeCompleto(cadastro[2]);
        usuario.setSenha(cadastro[3]);
        usuario.setEmail(cadastro[4]);
        usuario.setPontosExtra(0.0);
        for (int i = 0; i < cadastro.length; i++) {
            System.out.println(cadastro[i]);

        }

        String mensagemRetorno;
        try {
            try {
                // Objeto que vai ser transferido pelo socket
                UsuarioDao userDao = new UsuarioDao();

                if (userDao.buscaMatricula(cadastro[1]) == null) {

                    if (userDao.countAll() == 0) {
                        // Ninguem foi cadastrado ainda
                        usuario.setAdmin(true);
                        usuario.setStatus(1); // Usuario aceito
                        userDao.save(usuario);

                        // Responder ao cliente que o novo usuario eh admin
                        // e que foi adicionado com sucesso

                        out.writeUTF(protocoloMensagem.sucesso("Novo usuario administrador cadastrado"));
                    } else {
                        usuario.setStatus(0); // Usuario pendente
                        usuario.setAdmin(false);
                        userDao.update(usuario);
                       /* ArrayList<Usuario> admin = (ArrayList<Usuario>) userDao.listarAdmin();
                        for (Usuario usuario1 : admin) {
                            try {
                                Email email = new Email(usuario1.getEmail(), "Novo usuario Cadastrado", "Cadastro de Novo Usuario");
                                email.enviarPeloGmail();
                            } catch (Exception e) {
                                System.out.println("nao foi possivel enviar email");
                            }
                        }*/
                        mensagemRetorno = protocoloMensagem.sucesso("Novo usuario cadastrado, aguade ate que \n"
                                + "o administrador aceite sua solicitacao");
                        out.writeUTF(mensagemRetorno);
                    }
                } else {
                    mensagemRetorno = protocoloMensagem.codificarMensagemErro("Matricula ja cadastrada");
                    out.writeUTF(mensagemRetorno);
                }
            } catch (ConstraintViolationException e) {
                mensagemRetorno = protocoloMensagem.codificarMensagemErro("Erro: Matricula informada ja esta em uso \n"
                        + "Caso voce ja fez o cadastro, aguarde ate \n"
                        + "que o administrador aceite sua solicitacao");
                out.writeUTF(mensagemRetorno);
            } catch (Exception e) {
                mensagemRetorno = protocoloMensagem.codificarMensagemErro(e.getMessage().toString());
                out.writeUTF(mensagemRetorno);
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** metodo para validar Login de Usuario */
    private static void loginUsuario(String matricula, String senha,
            DataOutputStream out) {
        String mensagemRetorno;
        try {
            UsuarioDao vl = new UsuarioDao();
            Usuario user = vl.validateLogin(matricula, senha);
            if (user == null) {
                mensagemRetorno = protocoloMensagem.codificarMensagemErro("Matricula e/ou senha nao conferem");

            } else if (user.getStatus() == 0) {//Usuario pendente

                System.out.println("Usuario Pendente");
                mensagemRetorno = protocoloMensagem.codificarMensagemErro("Cadastro pendente. Aguarde o administraor aceitar sua solicitacao");

            } else {
                System.out.println("Usuario logado com sucesso");
                mensagemRetorno = protocoloMensagem.codificarMensageLogniSucesso(user.getMatricula(),
                        user.isAdmin());
            }
            System.out.println(mensagemRetorno);
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            System.out.println("Erro: " + e.getMessage());
        }
    }

    private static void receberPerguntaEnviada(String[] perguntaArray,
            DataOutputStream out) {
        Pergunta pergunta = new Pergunta();
        pergunta.setMensagem(perguntaArray[2]);
        pergunta.setTitulo(perguntaArray[1]);
        Date date = new Date();
        pergunta.setDataEnvio(date);
        UsuarioDao usuarioDAO = new UsuarioDao();
        Usuario usuario = usuarioDAO.buscaMatricula(perguntaArray[3]);
        pergunta.setUsuario(usuario);
        try {
            try {
                PerguntaDao perguntaDao = new PerguntaDao();
                perguntaDao.save(pergunta);
                out.writeUTF(protocoloMensagem.sucesso());

            } catch (Exception e) {
                out.writeUTF(protocoloMensagem.codificarMensagemErro(e.getMessage()));
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void getPerguntas(String[] arrayGetPerg,
            DataOutputStream out) {
        /** Utiliza o metodo protocolomensagem.get */
        PerguntaDao perguntaDao = new PerguntaDao();
        ArrayList<Object> objetos = (ArrayList<Object>) perguntaDao.getPerguntas(Integer.parseInt(arrayGetPerg[2]), Integer.parseInt(arrayGetPerg[3]), arrayGetPerg[1], Boolean.parseBoolean(arrayGetPerg[4]), arrayGetPerg[5], arrayGetPerg[6]);
        ArrayList<Pergunta> perguntas = (ArrayList<Pergunta>) objetos.get(1);
        Integer numeromaximo = (Integer) objetos.get(0);
        try {
            out.writeUTF(protocoloMensagem.codificarPerguntas(perguntas,
                    numeromaximo));
        } catch (IOException e) {
            try {
                out.writeUTF(protocoloMensagem.codificarMensagemErro(e.getMessage()));
            } catch (IOException e1) {

                e1.printStackTrace();
            }
            e.printStackTrace();
        }

    }

    private static void getUsuario(String matricula, DataOutputStream out) {
        String mensagemEnviar;
        UsuarioDao userDao = new UsuarioDao();

        Usuario usuario = userDao.buscaMatricula(matricula);
        mensagemEnviar = protocoloMensagem.codificarUsuario(
                usuario.getNomeCompleto(), usuario.getEmail());
        try {
            out.writeUTF(mensagemEnviar);
        } catch (IOException ex) {
            mensagemEnviar = protocoloMensagem.codificarMensagemErro(ex.getMessage());
            ex.printStackTrace();
        }
    }

    private static void alterarSenha(String[] mensagem, DataOutputStream out) {
        UsuarioDao login = new UsuarioDao();
        String mensagemRetorno;
        try {
            boolean user = login.alterarSenha(mensagem[1], mensagem[2],
                    mensagem[3]);
            if (user == false) {
                mensagemRetorno = protocoloMensagem.codificarMensagemErro("Senha não confere.");
            } else {
                System.out.println("Senha Alterada com Sucesso");
                mensagemRetorno = protocoloMensagem.sucesso();
            }
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void alterarUsuario(String[] mensagem, DataOutputStream out) {
        UsuarioDao login = new UsuarioDao();
        Usuario usuario = login.buscaMatricula(mensagem[1]);
        usuario.setEmail(mensagem[4]);
        usuario.setNomeCompleto(mensagem[2]);
        login.update(usuario);
        try {
            out.writeUTF(protocoloMensagem.sucesso());
        } catch (IOException ex) {
            Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    private static void getRespostadePergunta(String[] mensagemRecebida, DataOutputStream out) {
        RespostaDao dao = new RespostaDao();

        Collection<Resposta> respostas = (Collection<Resposta>) dao.getRespostas(Long.parseLong(mensagemRecebida[1]), mensagemRecebida[2]);
        String mensagemEnviar = protocoloMensagem.codificaRespostas(respostas,
                respostas.size());
        try {
            out.writeUTF(mensagemEnviar);
        } catch (IOException ex) {
            Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE,
                    null, ex);
        }
    }

    private static void responderPergunta(String[] mensagemRecebida, DataOutputStream out) {
        UsuarioDao usuarioDao = new UsuarioDao();
        Usuario usuario = new Usuario();
        usuario = usuarioDao.buscaMatricula(mensagemRecebida[2]);
        PerguntaDao perguntaDao = new PerguntaDao();
        Pergunta pergunta = perguntaDao.findByID(Long.parseLong(mensagemRecebida[3]));
        //--- Alterar status para Pergunta Respondida//Parcialmente respondida
        pergunta.setStatus(2); // Respondida e não avaliada
        perguntaDao.save(pergunta);
        Resposta resposta = new Resposta();
        resposta.setUsuario(usuario);
        resposta.setPergunta(pergunta);
        Date date = new Date();
        resposta.setDataEnvio(date);
        resposta.setMensagem(mensagemRecebida[1]);
        RespostaDao dao = new RespostaDao();
        dao.save(resposta);
        try {
            out.writeUTF(protocoloMensagem.sucesso("Pergunta Respondida com Sucesso."));
        } catch (IOException ex) {
            Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /*************** Administracao *****************/
    private static void getUsuariosAceitos(DataOutputStream out) {
        UsuarioDao user = new UsuarioDao();
        String mensagemRetorno;
        List<Usuario> listaUsuarios = (List) user.listarUserComPontuacao(null, null);
        mensagemRetorno = protocoloMensagem.codificarUsuarios(listaUsuarios);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void getUsuariosPendentes(DataOutputStream out) {
        UsuarioDao user = new UsuarioDao();
        String mensagemRetorno;

        List<Usuario> listaUsuarios = (List) user.listUsuariosPendentes();
        mensagemRetorno = protocoloMensagem.codificarUsuarios(listaUsuarios);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void atualizarUsuario(String objetoRecebido, DataOutputStream out) {
        Usuario usuario = protocoloMensagem.decodificarUsuario(objetoRecebido);
        Long id = usuario.getId();
        String mensagemRetorno = "";

        UsuarioDao userDao = new UsuarioDao();
        Usuario user = userDao.findByID(id);
        String senha = user.getSenha();
        usuario.setSenha(senha);
        userDao.save(usuario);
        System.out.println("Usuario atualizado");
        mensagemRetorno = protocoloMensagem.sucesso("Usuario atualizado com sucesso");
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void adminListarPerguntas(String status, DataOutputStream out) {
        String mensagemRetorno = "";
        PerguntaDao dao = new PerguntaDao();
        List<Pergunta> perguntas = null;
        int opcao = Integer.parseInt(status);
        switch (opcao) {
            case 0: // Listar todas perguntas
                perguntas = (List) dao.listAll();
                break;
            case 1: // Todas perguntas aceitas respondidas ou nao
                perguntas = (List) dao.listPerguntasAceitas();
                break;
            case 2:// Todas perguntas aceitas respondidas(correta, parcialmente ou respondida pendente)
                perguntas = (List) dao.listPerguntasRespondidas();
                break;
            case 3:// Todas perguntas aceitas respondidas corretamente apenas
                perguntas = (List) dao.listByStatus(3);
                break;
            case 4:// Todas perguntas aceitas respondidas parcialmente apenas
                perguntas = (List) dao.listByStatus(4);
                break;
            case 5:// Todas perguntas aceitas sem resposta
                perguntas = (List) dao.listByStatus(1);
                break;
            case 6:// Todas perguntas aceitas com respostas nao avaliadas
                perguntas = (List) dao.listByStatus(2);
                break;
            case 7: // Perguntas pendentes
                perguntas = (List) dao.listByStatus(0);
                break;
            case 8: // Perguntas deletadass
                perguntas = (List) dao.listByStatus(5);
                break;

        }
        mensagemRetorno = protocoloMensagem.adminCodificarListarPerguntas(perguntas);
        System.out.println(mensagemRetorno);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void adminListarRespostas(String pId, String op, DataOutputStream out) {
        String mensagemRetorno = "";
        RespostaDao respostaDao = new RespostaDao();
        List<Resposta> respostas = null;
        Long perguntaId = Long.parseLong(pId);
        int opcao = Integer.parseInt(op);
        switch (opcao) {
            case 0:
                respostas = (List) respostaDao.listAllFromPergunta(perguntaId);//Todas as respostas
                break;
            case 1:
                respostas = (List) respostaDao.listByStatusFromPergunta(perguntaId, 2);//Corretas
            case 2:
                respostas = (List) respostaDao.listByStatusFromPergunta(perguntaId, 1);//Parcialmente correta
            case 3:
                respostas = (List) respostaDao.listByStatusFromPergunta(perguntaId, 0);//Pendentes
            case 4:
                respostas = (List) respostaDao.listByStatusFromPergunta(perguntaId, 3);//Incorretas
                break;
        }


        mensagemRetorno = protocoloMensagem.adminCodificarRespostas(respostas);
        System.out.println(mensagemRetorno);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void atualizarStatusPergunta(Long perguntaId, int status, DataOutputStream out) {
        PerguntaDao dao = new PerguntaDao();
        Pergunta p = dao.findByID(perguntaId);
        p.setStatus(status);
        dao.save(p);
        String mensagemRetorno = protocoloMensagem.sucesso("Pergunta atualizada");
        System.out.println(mensagemRetorno);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void getPontuacao(String[] mensagemRecebida, DataOutputStream out) {
        UsuarioDao usuarioDao = new UsuarioDao();
        Double mensagemRetorno;
        if (mensagemRecebida.length > 2) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Integer.parseInt(mensagemRecebida[4]), Integer.parseInt(mensagemRecebida[3]) - 1, Integer.parseInt(mensagemRecebida[2]));
            Date date = calendar.getTime();
            calendar.set(Integer.parseInt(mensagemRecebida[7]), Integer.parseInt(mensagemRecebida[6]) - 1, Integer.parseInt(mensagemRecebida[5]));
            Date dateFinal = calendar.getTime();
            mensagemRetorno = usuarioDao.getMeusPontos(mensagemRecebida[1], date, dateFinal);
        } else {
            mensagemRetorno = usuarioDao.getMeusPontos(mensagemRecebida[1], null, null);
        }
        try {
            if (mensagemRetorno != null) {
                out.writeUTF(protocoloMensagem.sucesso(mensagemRetorno.toString()));
            } else {
                out.writeUTF(protocoloMensagem.sucesso("0"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
//TODO Terminar de implementar este metodo ele deve retorna o comentario da

    private static void getPerguntasStatus(String[] mensagemRecebida, DataOutputStream out) {
        PerguntaDao perguntaDao = new PerguntaDao();
        Collection<Pergunta> listByStatusAndUsuario = perguntaDao.listByStatusAndUsuario(mensagemRecebida[1], Integer.parseInt(mensagemRecebida[2]));
        if (listByStatusAndUsuario != null) {
            try {
                out.writeUTF(protocoloMensagem.codificarPerguntasByStatus(listByStatusAndUsuario, listByStatusAndUsuario.size()));
            } catch (IOException ex) {
                Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            try {
                out.writeUTF(protocoloMensagem.codificarPerguntasByStatus(listByStatusAndUsuario, 0));
            } catch (IOException ex) {
                Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private static void getRespostasStatus(String[] mensagemRecebida, DataOutputStream out) {
        RespostaDao respostaDao = new RespostaDao();
        Collection<Resposta> listByStatusAndUsuario = respostaDao.listByStatusAndUsuario(mensagemRecebida[1], Integer.parseInt(mensagemRecebida[2]));
        if (listByStatusAndUsuario != null) {
            try {
                out.writeUTF(protocoloMensagem.codificaRespostasByStatus(listByStatusAndUsuario, listByStatusAndUsuario.size()));
            } catch (IOException ex) {
                Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            try {
                out.writeUTF(protocoloMensagem.codificaRespostasByStatus(listByStatusAndUsuario, 0));
            } catch (IOException ex) {
                Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private static void comentarPergunta(String Id, String comentario, DataOutputStream out) {

        Long perguntaId = Long.parseLong(Id);
        PerguntaDao dao = new PerguntaDao();
        Pergunta p = dao.findByID(perguntaId);
        p.setComentario(comentario);
        dao.save(p);
        String mensagemRetorno = protocoloMensagem.sucesso("Comentario enviado com sucesso");
        System.out.println(mensagemRetorno);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void comentarResposta(String Id, String comentario, DataOutputStream out) {

        Long respostaId = Long.parseLong(Id);
        RespostaDao dao = new RespostaDao();
        Resposta r = dao.findByID(respostaId);
        r.setComentario(comentario);
        dao.save(r);
        String mensagemRetorno = protocoloMensagem.sucesso("Comentario enviado com sucesso");
        System.out.println(mensagemRetorno);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * Retorna os dez respostas com melhor pontuação
     * @param mensagemRecebida
     * @param out
     */
    private static void getRespostasNota(String[] mensagemRecebida, DataOutputStream out) {
        Collection<Resposta> listMaiorPontuacao;
        for (int i = 0; i < mensagemRecebida.length; i++) {
            System.out.println(mensagemRecebida[i]);
        }
        RespostaDao dao = new RespostaDao();
        if (mensagemRecebida.length > 1) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Integer.parseInt(mensagemRecebida[3]), Integer.parseInt(mensagemRecebida[2]) - 1, Integer.parseInt(mensagemRecebida[1]));
            Date date = calendar.getTime();
            calendar.set(Integer.parseInt(mensagemRecebida[6]), Integer.parseInt(mensagemRecebida[5]) - 1, Integer.parseInt(mensagemRecebida[4]));
            Date dateFinal = calendar.getTime();
            listMaiorPontuacao = dao.listMaiorPontuacao(10, date, dateFinal);
        } else {
            listMaiorPontuacao = dao.listMaiorPontuacao(10, null, null);
        }
        String codificaRespostas = protocoloMensagem.codificaRespostas(listMaiorPontuacao);
        try {
            out.writeUTF(codificaRespostas);
        } catch (IOException ex) {
            Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private static void getNotasUsuarios(String[] mensagemRecebida, DataOutputStream out) {
        Collection<Usuario> listMaiorPontuacao;

        UsuarioDao dao = new UsuarioDao();
        if (mensagemRecebida.length > 1) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Integer.parseInt(mensagemRecebida[3]), Integer.parseInt(mensagemRecebida[2]) - 1, Integer.parseInt(mensagemRecebida[1]));
            Date date = calendar.getTime();
            calendar.set(Integer.parseInt(mensagemRecebida[6]), Integer.parseInt(mensagemRecebida[5]) - 1, Integer.parseInt(mensagemRecebida[4]));
            Date dateFinal = calendar.getTime();
            listMaiorPontuacao = dao.listarUserComPontuacaoLimite(10, date, dateFinal);
        } else {
            listMaiorPontuacao = dao.listarUserComPontuacaoLimite(10, null, null);
        }
        String codificaRespostas = protocoloMensagem.codificarUsuarios(listMaiorPontuacao);
        try {
            out.writeUTF(codificaRespostas);
        } catch (IOException ex) {
            Logger.getLogger(AppServidor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private static void adminAtualizarResposta(String respId, String status, String nota, DataOutputStream out) {

        Long respostaId = Long.parseLong(respId);
        int novoStatus = Integer.parseInt(status);
        double pontuacao = Double.parseDouble(nota);

        RespostaDao respostaDao = new RespostaDao();
        Resposta r = respostaDao.findByID(respostaId);

        Long perguntaId = r.getPergunta().getId();
        PerguntaDao perguntaDao = new PerguntaDao();
        Pergunta p = perguntaDao.findByID(perguntaId);

        //Atualizar resposta... & status da pergunta
        switch (novoStatus) {
            case 0: // Resposta correta - status = 2
                r.setStatus(2);
                p.setStatus(3);
                break;
            case 1: // Resposta parcialmente correta - status = 1
                r.setStatus(1);
                if (p.getStatus() != 3) {
                    p.setStatus(4);
                }
                break;
            case 2: // Resposta incorreta - status = 3
                r.setStatus(5);
                break;
        }
        r.setPontuacao(pontuacao);
        respostaDao.save(r);
        perguntaDao.save(p);

        String mensagemRetorno = protocoloMensagem.sucesso("Resposta atualizada");
        System.out.println(mensagemRetorno);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void adminListarUsuarioComPontuacao(String objetoRecebido, DataOutputStream out) {
        UsuarioDao user = new UsuarioDao();
        String mensagemRetorno;
        System.out.println("Entrou aqui");
        List<Usuario> listaUsuarios = (List) user.listarUserComPontuacao(null, null);
        mensagemRetorno = protocoloMensagem.codificarUsuarios(listaUsuarios);
        try {
            out.writeUTF(mensagemRetorno);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
